package edu.ccut.saturn.component;

//import java.io.IOException;
//import java.io.InputStream;
//import java.net.URL;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;

/**
 * Data Object Manager. manager all data object in Bundles
 * 
 * @author 谷钰
 * @version 1.0 2008.09.09
 */
public class SaturnDataManager {

	private static final String KEY_SEPARATOR = "::";

	private static final String LOGGER_KEY_BUNDLE_SERVICE = SaturnLoggerManager.LOGGER_KEY_BUNDLE_SERVICE;

	protected static ILogger logger = SaturnLoggerManager.getInstance()
			.getSaturnLogger(LOGGER_KEY_BUNDLE_SERVICE);

	private static SaturnDataManager instance;

	static {
		instance = new SaturnDataManager();
	}

	// private XSDHelper xsdHelper;

	// private DataFactory dataFactory;

	private Map<String, Map<String, IDataInfo>> dataInfoMap;

	public SaturnDataManager() {
		// this.xsdHelper = XSDHelper.INSTANCE;
		// this.dataFactory = DataFactory.INSTANCE;
		this.dataInfoMap = new HashMap<String, Map<String, IDataInfo>>();
	}

	public static SaturnDataManager getInstance() {
		return instance;
	}

	/**
	 * Load data object from bundle
	 * 
	 * @param bundleInfo
	 */
	public void loadBundleData(IBundleInfo bundleInfo) {
		// this.loadDatas(bundleInfo.getBundleDataInfo().getDateUrls());
		this.loadDataInfos(bundleInfo.getBundleDataInfo().getDataInfos());
	}

	public void unLoadBundleData(IBundleInfo bundleInfo) {
		this.unLoadDataInfos(bundleInfo.getBundleDataInfo().getDataInfos());
	}

	/**
	 * Create DataObject
	 * 
	 * @param namespace
	 * @param dataType
	 * @return
	 */
	public SaturnData createData(String namespace, String dataType) {
		String dataFK = getSaturnDataFullKey(namespace,dataType);
		int index = dataFK.indexOf(KEY_SEPARATOR);
		String newNameSpace = dataFK.substring(0, index);
		String newDataType = dataFK.substring(index + 2);
		return createDataNoAdapt(newNameSpace, newDataType);
	}
	public SaturnData createDataNoAdapt(String namespace, String dataType) {
		SaturnData data = new SaturnData(namespace, dataType);
		data.setNamespace(namespace);
		data.setType(dataType);

		return data;
	}
	/**
	 * 根据指定的数据组件的全局键值创建SaturnData对象
	 * 
	 * @param dataFullKey
	 * @return
	 */
	public SaturnData createData(String dataFullKey) {
		if (isValidKey(dataFullKey)) {
			String dataFK = getSaturnDataFullKey(dataFullKey);
			int index = dataFK.indexOf(KEY_SEPARATOR);
			String namespace = dataFK.substring(0, index);
			String dataType = dataFK.substring(index + 2);
			return createDataNoAdapt(namespace, dataType);
		} else {
			return null;
		}
	}

	/**
	 * 找到适配数据库的数据项FK <br>
	 * <br>
	 * <b>适配规则:</b> FK + "_" + dbType
	 * 
	 * @param dataFullKey
	 * @return
	 */
	private String getSaturnDataFullKey(String dataFullKey) {
		IDatabaseConfigInfo databaseConfig = DatabaseManager.getInstance()
				.getDefaultDataBaseConfigInfo();

		if (databaseConfig != null) {
			String dbType = databaseConfig.getDbType();

			String adapterFullKey = dataFullKey + "_" + dbType.toUpperCase();
			IDataInfo dataInfo = SaturnDataManager.getInstance()
					.getSaturnDataInfoNoAdapt(adapterFullKey);

			if (dataInfo != null) {
				return adapterFullKey;
			}
		}

		return dataFullKey;
	}
	private String getSaturnDataFullKey(String nameSpace,String type) {
		return getSaturnDataFullKey(nameSpace+"::"+type);
	}
	/**
	 * 获得指定命名空间和名称的数据组件的信息
	 * 
	 * @param namespace
	 * @param dataType
	 * @return
	 */
	public IDataInfo getSaturnDataInfo(String namespace, String dataType) {
		String dataFK = getSaturnDataFullKey(namespace,dataType);
		return getSaturnDataInfoNoAdapt(dataFK) ;
//		Map<String, IDataInfo> dataInfos = this.dataInfoMap.get(namespace);
//
//		if (dataInfos != null) {
//			return dataInfos.get(dataType);
//		}
//
//		return null;
	}
	public IDataInfo getSaturnDataInfoNoAdapt(String namespace, String dataType) {
		Map<String, IDataInfo> dataInfos = this.dataInfoMap.get(namespace);

		if (dataInfos != null) {
			return dataInfos.get(dataType);
		}

		return null;
	}
	public Set<String> getSaturnDataInfoNamespaceKeys() {
		return this.dataInfoMap.keySet();
	}

	public Set<String> getSaturnDataInfoKeys(String namespace) {
		Map<String, IDataInfo> namespaceDataInfoMap = this.dataInfoMap
				.get(namespace);

		if (namespaceDataInfoMap != null) {
			return namespaceDataInfoMap.keySet();
		}

		return null;
	}

	/**
	 * 通过数据组件的全局键值获得数据组件信息
	 * 
	 * @param dataFullKey
	 * @return
	 */
	public IDataInfo getSaturnDataInfo(String dataFullKey) {
		if (isValidKey(dataFullKey)) {
			String dataFK = getSaturnDataFullKey(dataFullKey);
			int index = dataFK.indexOf(KEY_SEPARATOR);
			String namespace = dataFK.substring(0, index);
			String dataType = dataFK.substring(index + 2);
			return getSaturnDataInfoNoAdapt(namespace, dataType);
		} else {
			return null;
		}
	}

	//
	private IDataInfo getSaturnDataInfoNoAdapt(String dataFullKey) {
		if (isValidKey(dataFullKey)) {
			int index = dataFullKey.indexOf(KEY_SEPARATOR);
			String namespace = dataFullKey.substring(0, index);
			String dataType = dataFullKey.substring(index + 2);
			return getSaturnDataInfoNoAdapt(namespace, dataType);
		} else {
			return null;
		}
	}

	// private void loadData(URL url) {
	// if (url != null) {
	// InputStream in = null;
	//
	// try {
	// in = url.openStream();
	// // TODO:define method second parameter why null?
	// this.xsdHelper.define(in, null);
	// logger.debug("load data : " + url);
	// } catch (IOException e) {
	// e.printStackTrace();
	// } finally {
	// if (in != null) {
	// try {
	// in.close();
	// } catch (IOException e) {
	// e.printStackTrace();
	// }
	// }
	// }
	// }
	// }
	//
	// public void loadDatas(List<URL> urls) {
	// for (URL url : urls) {
	// this.loadData(url);
	// }
	// }

	/**
	 * 添加数据组件信息列表
	 */
	public void loadDataInfos(List<IDataInfo> dataInfos) {
		if (dataInfos != null) {
			for (IDataInfo dataInfo : dataInfos) {
				loadDataInfo(dataInfo);
			}
		}
	}

	/**
	 * 添加数据组件信息
	 * 
	 * @param dataInfo
	 */
	public void loadDataInfo(IDataInfo dataInfo) {
		String space = dataInfo.getSpace();
		if (this.dataInfoMap.containsKey(space)) {
			this.dataInfoMap.get(space).put(dataInfo.getType(), dataInfo);

		} else {
			Map<String, IDataInfo> infos = new HashMap<String, IDataInfo>();
			infos.put(dataInfo.getType(), dataInfo);
			this.dataInfoMap.put(space, infos);
		}
	}

	/**
	 * 从内存中卸载组件信息列表
	 * 
	 * @param dataInfos
	 */
	public void unLoadDataInfos(List<IDataInfo> dataInfos) {
		for (IDataInfo dataInfo : dataInfos) {
			this.unLoadDataInfo(dataInfo);
		}
	}

	/**
	 * 从内存中卸载单个组件信息
	 * 
	 * @param dataInfo
	 */
	public void unLoadDataInfo(IDataInfo dataInfo) {
		if (this.dataInfoMap.containsKey(dataInfo.getSpace())) {
			Map<String, IDataInfo> infos = this.dataInfoMap.get(dataInfo
					.getSpace());

			if (infos.containsKey(dataInfo.getType())) {
				infos.remove(dataInfo.getType());
			}
		}
	}

	private boolean isValidKey(String dataFullKey) {
		int index = dataFullKey.indexOf(KEY_SEPARATOR);
		if (index == -1 || index == 0 || index == dataFullKey.length() - 2) {
			try {
				throw new SaturnComponentException(dataFullKey
						+ " is not a valid key");
			} catch (SaturnComponentException e) {
				e.printStackTrace();
				return false;
			}
		}
		return true;
	}
}
